package com.jeesuite.apigateway.filter;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.io.CharStreams;
import com.jeesuite.passport.LoginContext;
import com.jeesuite.springweb.WrapperResponseEntity;
import com.netflix.util.Pair;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;


/**
 * 
 * @description <br>
 * @author <a href="mailto:vakinge@gmail.com">vakin</a>
 * @date 2017年6月15日
 */
public class ResponseWrapFilter extends ZuulFilter {
	
	private static final String CONTENT_TYPE = "Content-Type";
	private static final String DEFAULT_ERR_MSG = "/(ㄒoㄒ)/~~System error";
	private static final String _MESSAGE_NAME = "message";
	private static final String _CODE_NAME = "code";
	private static final String CHARTSET_UTF_8 = "UTF-8";
	private static Logger log = LoggerFactory.getLogger(ResponseWrapFilter.class);
	private static ObjectMapper mapper = new ObjectMapper();
	
	static{
		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
	}
	
    @Override
    public String filterType() {
        return "post";
    }

    @Override
    public int filterOrder() {
        return 9;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        
        try {
        	List<Pair<String, String>> headers = ctx.getOriginResponseHeaders();
        	for (Pair<String, String> pair : headers) {
        		if(CONTENT_TYPE.equals(pair.first()) && pair.second().contains(MediaType.TEXT_HTML_VALUE)){
        			return null;
        		}
        	}

        	InputStream responseDataStream = ctx.getResponseDataStream();
        	
            int statusCode = ctx.getResponseStatusCode();
            
            
            final String responseData = responseDataStream == null ? null : CharStreams.toString(new InputStreamReader(responseDataStream, CHARTSET_UTF_8));
            
            JsonNode jsonNode = null;
            try {	
            	if(responseData != null){            		
            		jsonNode = mapper.readTree(responseData);
            		JsonNode codeNode = jsonNode.get(_CODE_NAME);
            		if(codeNode != null){ //业务异常
            			ctx.setResponseStatusCode(200);
            			ctx.setResponseBody(responseData);
            			return null;
            		}
            	}
			} catch (Exception e) {}
            
            WrapperResponseEntity responseModel = new WrapperResponseEntity();
            responseModel.setCode(statusCode);
            
            if(statusCode == 200){
            	responseModel.setData(jsonNode == null ? responseData : jsonNode);
            }else{
            	String errorMsg = null;
            	try {errorMsg = jsonNode.get(_MESSAGE_NAME).textValue();} catch (Exception e) {}
            	if(errorMsg == null){
            		try {errorMsg = HttpStatus.valueOf(statusCode).getReasonPhrase();} catch (Exception e) {}
            	}
            	if(errorMsg == null)errorMsg = DEFAULT_ERR_MSG;
            	responseModel.setMsg(errorMsg);
            }
            ctx.setResponseBody(mapper.writeValueAsString(responseModel));

        } catch (Exception e) {
        	log.error("ResponseWrapFilter error",e);
        }finally {
        	MDC.clear();
        	LoginContext.resetLoginSessionHolder();
		}
     
        return null;
    }
}

